﻿using Dapper;
using Dapper.Contrib.Extensions;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wechat.Util.Paged;

namespace Wechat.Dao.Implement
{
    /// <summary>
    /// 仓储操作基础类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class RepositoryBase<T> : IRepository<T> where T : class
    {
        internal SqlConnection Connection
        {
            get
            {
                return new SqlConnection(ConfigurationManager.ConnectionStrings["WechatSqlConnection"].ConnectionString);
            }
        }

        /// <summary>
        /// 获取实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual T Get(int id)
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                return cn.Get<T>(id);
            }
        }

        /// <summary>
        /// 获取实体
        /// </summary>
        /// <param name="table">根据字段</param>
        /// <param name="key">根据字段</param>
        /// <param name="value">字段值</param>
        /// <returns></returns>
        public virtual IList<T> GetByKey(string table, string key, object value)
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                return cn.Query<T>(
                    string.Format("select * from {0} where {1}=@field", table, key), new { field = value }).ToList();
            }
        }

        /// <summary>
        /// 获取全部实体
        /// </summary>
        /// <returns></returns>
        public virtual IList<T> GetAll()
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                return cn.GetAll<T>().ToList();
            }
        }

        /// <summary>
        /// 插入实体
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual int Insert(T obj)
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                return Convert.ToInt32(cn.Insert<T>(obj));
            }
        }

        /// <summary>
        /// 批量插入实体
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual int Insert(IEnumerable<T> list)
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                return Convert.ToInt32(cn.Insert(list));
            }
        }

        /// <summary>
        /// 批量插入实体事务
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public virtual int InsertTran(IEnumerable<T> list)
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                IDbTransaction tran = cn.BeginTransaction();
                try
                {
                    return Convert.ToInt32(cn.Insert(list, tran));
                }
                catch (Exception ex)
                {
                    tran.Rollback();
                    return 0;
                }
                finally
                {
                    tran.Commit();
                }
            }
        }

        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual bool Update(T obj)
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                return cn.Update<T>(obj);
            }
        }

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual bool Delete(T obj)
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                return cn.Delete<T>(obj);
            }
        }

        /// <summary>
        /// 条件查询
        /// </summary>
        /// <param name="query"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual IList<T> LoadByCondition(string query, object param)
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                return cn.Query<T>(query, param).ToList();
            }
        }

        /// <summary>
        /// 根据条件分页查询
        /// </summary>
        /// <param name="criteria">分页请求参数</param>
        /// <returns></returns>
        public virtual PagedList<TModel> GetPageDataList<TModel>(PageCriteria criteria) where TModel : class
        {
            var dp = new DynamicParameters();
            dp.AddDynamicParams(criteria);
            dp.Add("RecordCount", dbType: DbType.Int32, direction: ParameterDirection.Output);
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                var pageData = new PagedList<TModel>();
                pageData.CurrentPageItems = cn.Query<TModel>("[dbo].[ProcGetPageData]", dp, commandType: CommandType.StoredProcedure).ToList();
                pageData.TotalItemCount = dp.Get<int>("RecordCount");
                pageData.TotalPageCount = Convert.ToInt32(Math.Ceiling(pageData.TotalItemCount * 1.0 / criteria.PageSize));
                pageData.CurrentPageIndex = criteria.CurrentPage > pageData.TotalPageCount ? pageData.TotalPageCount : criteria.CurrentPage;
                return pageData;
            }
        }

        /// <summary>
        /// 执行简单存储过程，返回受影响行数
        /// </summary>
        /// <param name="param"></param>
        /// <param name="procName"></param>
        /// <returns></returns>
        public virtual int ExecByProcedure(object param, string procName)
        {
            var dp = new DynamicParameters();
            dp.AddDynamicParams(param);
            using (IDbConnection con = Connection)
            {
                return con.Execute(procName, dp, null, null, CommandType.StoredProcedure);
            }
        }

        /// <summary>
        /// 执行sql，返回受影响的行数
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="param">参数对象</param>
        /// <returns></returns>
        public virtual int ExecuteSql(string sql, object param = null)
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                return cn.Execute(sql, param);
            }
        }

        /// <summary>
        /// 执行sql，返回一行一列值
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="param">参数对象</param>
        /// <returns></returns>
        public virtual object ExecuteScalar(string sql, object param = null)
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                return cn.ExecuteScalar(sql, param);
            }
        }

        /// <summary>
        /// 根据SQL查询
        /// </summary>
        /// <typeparam name="M">查询实体类型</typeparam>
        /// <param name="sql">SQL语句</param>
        /// <param name="param">参数对象</param>
        /// <returns></returns>
        public virtual IList<M> Query<M>(string sql, object param = null) where M : class
        {
            using (IDbConnection cn = Connection)
            {
                cn.Open();
                return cn.Query<M>(sql, param).ToList();
            }
        }
    }
}
